/**
    ATClab - scriptable Air Traffic Control simulations.
    Copyright (C) 2010 openatclab@gmail.com

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

#ifndef __ATC_CANVAS_ACTION_HDR__ 
#define __ATC_CANVAS_ACTION_HDR__

#include <qobject.h>
//Added by qt3to4:
#include <QLabel>
#include <QEvent>

#include "aircraft_data.h"
#include "scale.h"
#include "conflictdeclaration.h"

#include <q3canvas.h>
#include <map>
#include <vector>

class QDialog;
class QLabel;
class QPushButton;

namespace atc
{
	class CanvasView;
	class EngineImpl;

	/*!
	 * Base Class
	 */
	class CanvasEventHandler : public QObject {
		Q_OBJECT
	public:
		CanvasEventHandler( CanvasView *, Q3CanvasItem * = 0 ); 
		virtual ~CanvasEventHandler() {};

		virtual void setItem( Q3CanvasItem *i ) { m_item = i; }
		virtual void onLoad() {};
		virtual void onUnload() {};
		virtual bool action( QEvent * ) = 0;

	protected:
		void activate_pointer( bool );
		void unload();
		void clear_tool();
		void update();

	protected:
		CanvasView  *m_view;
		Q3CanvasItem *m_item;
	};


	/*!
	 *
	 */
	struct CanvasEventHandlerBuilder {
		virtual CanvasEventHandler* operator()( CanvasView *, EngineImpl * ) = 0;
	};
	

	/*!
	 *
	 */
	class PauseToolHandler : public CanvasEventHandler {
		Q_OBJECT
	public:
		PauseToolHandler( CanvasView *v ) : CanvasEventHandler(v) {};
	public:
		void onLoad();
		bool action( QEvent * ) { return false; };
	};


	/*!
	 *
	 */
	class ResumeToolHandler : public CanvasEventHandler {
		Q_OBJECT
	public:
		ResumeToolHandler( CanvasView *v ) : CanvasEventHandler(v) {};
	public:
		void onLoad();
		bool action( QEvent * ) { return false; };
	};


	/*!
	 *
	 */
	class ScaleHandler : public CanvasEventHandler {
		Q_OBJECT
	public:
		ScaleHandler( CanvasView * );
	public:
		virtual void setItem( Q3CanvasItem * );
		virtual bool action( QEvent * );
	private:
		ScaleXHair  *_scale;
		QPoint		 _cursor;
	};

	
	/*!
	 *
	 */
	class ScaleHandlerBuilder : public CanvasEventHandlerBuilder {
	public:
		ScaleHandlerBuilder( bool fixed = false ) : _fixed( fixed ) {}
		CanvasEventHandler* operator()( CanvasView *cv, EngineImpl * ) { 
				return _fixed ? 0 : new ScaleHandler(cv); 
			};
	private:
		bool _fixed;
	};

	/*!
	 *
	 */
	class AircraftAgent;

	struct AircraftDeclarationText
	{
		AircraftDeclarationText(	unsigned int a_row = 0, 
									const std::string& a_text = "")
			:	m_row(a_row),
				m_text(a_text)
		{
		}

		unsigned short	m_row;
		std::string		m_text;
	};

	enum ADB_TYPE
	{
		ADB_TYPE_UNKNOWN,
		ADB_TYPE_CONFLICT,
		ADB_TYPE_NON_CONFLICT,
		ADB_TYPE_CANCEL
	};

	struct AircraftDeclarationButton
	{
		AircraftDeclarationButton(	const std::string& a_name,
									const std::string& a_type,
									const std::string& a_label)
			:	m_name(a_name),
				m_label(a_label)
		{
			if (a_type == "conflict")
			{
				m_type = ADB_TYPE_CONFLICT;
			}
			else if (a_type == "non-conflict")
			{
				m_type = ADB_TYPE_NON_CONFLICT;
			}
			else if (a_type == "cancel")
			{
				m_type = ADB_TYPE_CANCEL;
			}
			else
			{
				m_type = ADB_TYPE_UNKNOWN;
			}
		}

		std::string m_name;
		std::string m_label;
		ADB_TYPE	m_type;
	};

	struct AircraftDeclaration
	{
		std::vector<AircraftDeclarationButton>  m_buttons;
		std::vector<AircraftDeclarationText>	m_texts;
	};

	const std::string AC_SUBSTITUTE_STRING = "^";

	class AltitudeHandler : public CanvasEventHandler 
	{
		Q_OBJECT
	
	public:
		AltitudeHandler(CanvasView *, AircraftDeclaration a_ad, int = -1, int = -1);

		virtual void setItem(Q3CanvasItem*);
		virtual bool action(QEvent*);
	
	signals:
		void sig_conflict_identified(	const std::string&		a_callsign1, 
										const std::string&		a_callsign2);

		void sig_non_conflict_identified(	const std::string&	a_callsign1,
											const std::string&	a_callsign2);

	public slots:
		void resolve();

	private:
		void buildDialog();
		void cleanUp();
		void conflictDeclaration();
		void GetDisplayText(const std::string& a_text,
							std::vector<std::string>& a_tokens,
							const std::string& delimiters = AC_SUBSTITUTE_STRING);

	private slots:
		void conflictDeclared();
		void nonConflictDeclared();
		void reject();

 	private:
		static const int RESOLUTION_ALTITUDE_DELTA;

		bool						m_isDeclaring;
		AircraftAgent*				m_agent;
		QDialog*					m_dialog;
		QLabel*						m_callsign1;
		QLabel*						m_callsign2;
		QPushButton*				m_conflict;
		QPushButton*				m_nonConflict;
		int							m_x;
		int							m_y;
		std::vector<ControlState>	m_actionStates;
		AircraftDeclaration			m_aircraftDeclaration;
	};

	/*!
	 *
	 */
	class AltitudeHandlerBuilder : public CanvasEventHandlerBuilder 
	{
	public:
		AltitudeHandlerBuilder() : CanvasEventHandlerBuilder(), _x(-1), _y(-1), m_aircraftDeclaration() {}
	public:
		virtual CanvasEventHandler* operator()( CanvasView *, EngineImpl * );
	public:
		AltitudeHandlerBuilder* setXY( int x, int y ) { _x = x; _y = y; return this; }
		
		void SetAircraftDeclaration(AircraftDeclaration a_ad) { m_aircraftDeclaration = a_ad; }

	private:
		int _x, _y;
		AircraftDeclaration m_aircraftDeclaration;
	};

	/*!
	 *
	 */
	class VelocityHandler : public CanvasEventHandler {
		Q_OBJECT

	public:
		VelocityHandler( CanvasView * );

	public:
		virtual void setItem( Q3CanvasItem * );
		virtual bool action( QEvent * );

	public slots:
		void resolve();

	private:
		void build_dialog();
		void conflict_resolution();

	private slots:
		void accept();
		void reject();

	private:
		bool			 _isResloving;
		AircraftAgent	*_agent;
		QDialog			*_dialog;
		QLabel			*_resolveCall;
		QLabel			*_conflictCall;
	};

	struct VelocityHandlerBuilder : CanvasEventHandlerBuilder {
		virtual CanvasEventHandler* operator()( CanvasView *cv, EngineImpl * ) { 
				return new VelocityHandler(cv); 
			};
	};


	/*!
	 *
	 */
	class RotateCalloutHandler : public CanvasEventHandler {
		Q_OBJECT

	public:
		RotateCalloutHandler( CanvasView *v ) : CanvasEventHandler(v) {};


	public:
		virtual bool action( QEvent * );

	};


	/*!
	 *
	 */
	class AircraftSprite;

	/*!
	 *
	 */
	class ACToolsHandler : public CanvasEventHandler {
		Q_OBJECT

	public:
		ACToolsHandler( CanvasView *v ) : CanvasEventHandler(v) {}

	public:
		virtual bool action( QEvent * );
	};


	/*!
	 *
	 */
	class VectorTool;

	/*!
	 *
	 */
	class VectorToolHandler : public CanvasEventHandler {
		Q_OBJECT

	public:
		VectorToolHandler( CanvasView * );

	public:
		virtual bool action( QEvent * );

	private:
		void unload();

	private:
		VectorTool *_vector;
	};

	/*!
	 *
	 */
	class BearingRangeLine;

	/*!
	 *
	 */
	class BRLToolHandler : public CanvasEventHandler {
		Q_OBJECT

	public:
		BRLToolHandler( CanvasView * );

	public:
		virtual void setItem( Q3CanvasItem * );
		virtual bool action( QEvent * );

	private:
		BearingRangeLine *_brline;
	};
}

#endif
